package com.karaoke.android.data.websocket

import com.alibaba.fastjson.JSON
import com.apkfuns.logutils.LogUtils
import com.karaoke.android.data.domain.*
import com.karaoke.android.data.krealmextensions.saveAll
import com.karaoke.android.data.service.MediaListService
import com.karaoke.android.data.utils.getDeviceSN
import okhttp3.*
import okio.ByteString
import org.simple.eventbus.EventBus
import rx.Observable
import java.util.concurrent.TimeUnit
import kotlin.properties.Delegates


/**
 * Created by Administrator on 2017/4/11.
 */

class WebSocketClient(private val address: String) : WebSocketListener()
{
    init
    {
        EventBus.getDefault().register(this)
    }

    private var webSocket: WebSocket? = null


    private var httpClient: OkHttpClient by Delegates.notNull()

    fun onConnect()
    {
        val sn = getDeviceSN()
        val request = Request.Builder().url("ws://$address:8899/ws/room/$sn").build()
        httpClient = OkHttpClient().newBuilder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build()
        httpClient.newWebSocket(request, this)
        httpClient.dispatcher().executorService().shutdown()
    }

    fun onClose()
    {
        webSocket?.close(1000, null)
    }

    override fun onOpen(webSocket: WebSocket?, response: Response?)
    {
        super.onOpen(webSocket, response)
        this.webSocket = webSocket
        LogUtils.e("webSocket 连接成功")
        EventBus.getDefault().post(StateChanged(State.Opened))
    }


    override fun onClosed(webSocket: WebSocket?, code: Int, reason: String?)
    {
        super.onClosed(webSocket, code, reason)
        LogUtils.e("webSocket 断开")
        EventBus.getDefault().post(StateChanged(State.Closed))
    }

    override fun onClosing(webSocket: WebSocket?, code: Int, reason: String?)
    {
        super.onClosing(webSocket, code, reason)
        LogUtils.e("webSocket 关闭中")
        EventBus.getDefault().post(StateChanged(State.Closing))
    }

    override fun onMessage(webSocket: WebSocket?, bytes: ByteString?)
    {
        super.onMessage(webSocket, bytes)
    }

    override fun onMessage(webSocket: WebSocket?, text: String)
    {
        super.onMessage(webSocket, text)
        LogUtils.e("webSocket 接收消息 ： $text")
        try
        {
            val jsonObject = JSON.parseObject(text)
            val cmd = jsonObject.getString("cmd")
            when (Command.valueOf(cmd))
            {

                Command.RoomInit    ->
                {
                    val data = JSON.parseObject(jsonObject.getString("value"), DeviceData::class.java)
                    EventBus.getDefault().post(data)
                }
                Command.PublicSongs ->
                {
                    val data = JSON.parseObject(jsonObject.getString("value"), SongList::class.java)
                    MediaListService.publicSongs = data
                }
                Command.ScrollTexts ->
                {
                    val data = JSON.parseObject(jsonObject.getString("value"), ScrollTextList::class.java)
                    data.saveAll()
                }
                else                ->
                {
                }
            }
        }
        catch (e: Exception)
        {
            e.printStackTrace()
        }
    }

    override fun onFailure(webSocket: WebSocket?, t: Throwable?, response: Response?)
    {
        super.onFailure(webSocket, t, response)
        LogUtils.e("webSocket 链接失败 ${t?.message}  $response")
        EventBus.getDefault().post(StateChanged(State.Failure))

    }

//    fun onReceiveUdpMessage(data: DatagramPacket): Observable<Void>
//    {
//        val message = JSON.parseObject(data.content().toString(Charset.defaultCharset()), UdpMessage::class.java)
//        EventBus.getDefault().post(message, message.cmd)
//        return Observable.never()
//    }

    fun sendMessage(text: String)
    {
        webSocket?.send(text)
    }

    fun sendMessage(message: com.karaoke.android.data.domain.Message<*>)
    {
        LogUtils.e(message)
        sendMessage(message.toJson())
    }

//    fun sendUdpMessage(message: UdpMessage)
//    {
//        val value = message.toJson()
//        val packet = DatagramPacket(Unpooled.buffer().writeBytes(value.toByteArray()), InetSocketAddress("192.168.1.252", 8088))
//        serverConnect?.writeAndFlush(packet)
//    }

    fun onUdpError(error: Throwable): Observable<Void>
    {
        error.printStackTrace()
        return Observable.never()
    }


    enum class State
    {
        Opened,
        Closed,
        Closing,
        Failure
    }

    class StateChanged(val state: State)

    class ReceiveMessage(val webSocket: WebSocket?, val command: Command)
}

private fun <T> Message<T>.toJson(): String
{
    return JSON.toJSONString(this)
}
